package com.etonenet.controller.system;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.etonenet.entity.system.SysLog;
import com.etonenet.entity.system.SystemNode;
import com.etonenet.entity.system.Url;
import com.etonenet.entity.system.UrlAction;
import com.etonenet.entity.system.security.Role;
import com.etonenet.entity.system.security.UserBs;
import com.etonenet.entity.system.security.UserGroup;
import com.etonenet.enums.systemnode.SystemNodeType;
import com.etonenet.repository.system.UrlActionRepository;
import com.etonenet.repository.system.security.RoleUserRepository;
import com.etonenet.repository.system.security.UserBsRepository;
import com.etonenet.repository.system.security.UserGroupRepository;
import com.etonenet.service.system.MenuService;
import com.etonenet.service.system.RoleService;
import com.etonenet.service.system.SysLogService;
import com.etonenet.service.system.UrlService;
import com.etonenet.service.system.UserBsService;
import com.etonenet.service.system.UserGroupService;
import com.etonenet.taglibs.component.AjaxPage;
import com.etonenet.taglibs.util.AjaxPageUtil;
import com.etonenet.util.DateUtil;
import com.etonenet.util.StringUtil;

import esms.etonenet.boss1069.enums.LogicStat;
import esms.etonenet.boss1069.enums.syslog.OperType;
import esms.etonenet.boss1069.enums.usergroup.IsMenu;
import esms.etonenet.boss1069.util.AutocompleteUtil;
import esms.etonenet.boss1069.util.TilesUtil;
import esms.etonenet.boss1069.web.Autocomplete;
import esms.etonenet.boss1069.web.PageRequest;
import esms.etonenet.boss1069.web.SpecificationCondition;
import esms.etonenet.boss1069.web.SpecificationHelper;
import esms.etonenet.boss1069.web.UrlConstants;
import springfox.documentation.annotations.ApiIgnore;

@ApiIgnore
@Controller
public class SystemController {

	@Resource
	private UserGroupRepository userGroupEm;

	@Resource
	private UrlActionRepository urlActionEm;

	@Resource
	private UserGroupService userGroupService;

	@Resource
	private UrlService urlService;

	@Resource
	private MenuService menuService;

	@Resource
	private SysLogService sysLogService;

	@Resource
	private RoleService roleService;

	@Resource
	private RoleUserRepository roleUserEm;

	@Resource
	private UserBsRepository userBsEm;

	@Resource
	private UserBsService userBsService;

	@RequestMapping(UrlConstants.SYSTEM_AUTH_INDEX)
	public ModelAndView sysAuthIndex() {

		ModelAndView mv = new ModelAndView(TilesUtil.getPath(UrlConstants.SYSTEM_AUTH_INDEX));
		return mv;
	}

	@ResponseBody
	@RequestMapping(UrlConstants.SYSTEM_AUTH_DATA)
	public AjaxPage sysAuthData(Integer pageNumber, Integer pageSize, String displayName, String sortName,
			String sortOrder) {

		List<SpecificationCondition> conditions = new ArrayList<>();
		conditions.add(SpecificationCondition.equalOrLikeIgnoreCase("displayName", displayName));

		SpecificationHelper<Role> sh = new SpecificationHelper<>(conditions, sortOrder, sortName);

		Page<?> p = roleService.page(new PageRequest(pageNumber, pageSize), sh.createSpecification());
		return AjaxPageUtil.toAjaxPage(p.getTotalElements(), p.getContent());
	}

	@ResponseBody
	@RequestMapping(UrlConstants.SYSTEM_AUTH_SAVE)
	public String sysAuthData(Long roleid, String... data) {

		List<Long> userIds = new ArrayList<>();
		for (String id : data) {
			if (StringUtil.isNotEmpty(id))
				userIds.add(Long.valueOf(id));
		}

		userBsService.saveRoleUsers(roleid, userIds);
		return "保存成功";
	}

	@RequestMapping(UrlConstants.SYSTEM_AUTH_ROLEUSER)
	public ModelAndView sysAuthRoleUser(Long roleid) {

		ModelAndView mv = new ModelAndView(UrlConstants.SYSTEM_AUTH_ROLEUSER);

		List<UserBs> roleUsers = userBsEm.listUsersByRoleId(roleid);
		List<UserBs> noroleUsers = new ArrayList<>();

		for (UserBs u : userBsEm.listAllUser())
			if (!roleUsers.contains(u))
				noroleUsers.add(u);

		mv.addObject("noroleUsers", noroleUsers);
		mv.addObject("roleUsers", roleUsers);
		mv.addObject("roleid", roleid);

		return mv;
	}

	@RequestMapping(UrlConstants.SYSTEM_LOG_INDEX)
	public ModelAndView sysLogIndex() {

		ModelAndView mv = new ModelAndView(TilesUtil.getPath(UrlConstants.SYSTEM_LOG_INDEX));
		mv.addObject("operType", OperType.toDisplayMap());

		return mv;
	}

	@ResponseBody
	@RequestMapping(UrlConstants.SYSTEM_LOG_DATA)
	public AjaxPage sysLogData(Integer pageNumber, Integer pageSize, SysLog search, String operUserStr,
			String timeStart, String timeEnd, String sortName, String sortOrder) throws ParseException {

		List<SpecificationCondition> conditions = new ArrayList<>();
		conditions.add(SpecificationCondition.equalOrLikeIgnoreCase("classId", search.getClassId()));
		conditions.add(SpecificationCondition.equalOrLikeIgnoreCase("className", search.getClassName()));
		if (StringUtil.isNotEmpty(operUserStr))
			conditions.add(SpecificationCondition.eq("operUser.userId", operUserStr.split("-")[0]));
		conditions.add(SpecificationCondition.eq("oper", search.getOper()));
		conditions.add(SpecificationCondition.equalOrLikeIgnoreCase("prop", search.getProp()));
		if (StringUtil.isNotEmpty(timeStart) || StringUtil.isNotEmpty(timeEnd)) {
			Date start = new Date(0);
			Date end = new Date();
			if (StringUtil.isNotEmpty(timeStart))
				start = DateUtil.parseDate(timeStart, "yyyy-MM-dd");
			if (StringUtil.isNotEmpty(timeEnd))
				end = DateUtil.parseDate(timeEnd, "yyyy-MM-dd");
			conditions.add(SpecificationCondition.between("logTime", start, end));
		}

		if (StringUtil.isEmpty(sortName)) {
			sortOrder = "desc";
			sortName = "logTime";
		}

		SpecificationHelper<SysLog> sh = new SpecificationHelper<>(conditions, sortOrder, sortName);

		Page<?> p = sysLogService.page(new PageRequest(pageNumber, pageSize), sh.createSpecification());
		return AjaxPageUtil.toAjaxPage(p.getTotalElements(), p.getContent());
	}

	@RequestMapping(UrlConstants.SYSTEM_LOG_AUTOCOMPLETE_OPERUSER)
	@ResponseBody
	public List<Autocomplete> autoOperUser(String term) {

		return AutocompleteUtil.object2auto(userBsEm.auto(term));
	}

	@RequestMapping(UrlConstants.SYSTEM_NODE_INDEX)
	public ModelAndView nodeIndex() {

		ModelAndView mv = new ModelAndView(TilesUtil.getPath(UrlConstants.SYSTEM_NODE_INDEX));
		mv.addObject("nodetree", menuService.listTreegrid());

		return mv;
	}

	@RequestMapping(UrlConstants.SYSTEM_NODE_NEW)
	public ModelAndView nodeNew(String parentid) {

		ModelAndView mv = new ModelAndView(UrlConstants.SYSTEM_NODE_NEW);
		mv.addObject("parentid", parentid);
		mv.addObject("systemNodeType", SystemNodeType.toDisplayMap());
		return mv;
	}

	@RequestMapping(UrlConstants.SYSTEM_NODE_VIEW)
	public ModelAndView nodeView(Long nodeid) {

		ModelAndView mv = new ModelAndView(UrlConstants.SYSTEM_NODE_VIEW);
		mv.addObject("node", menuService.findByNodeId(nodeid));
		mv.addObject("systemNodeType", SystemNodeType.toDisplayMap());
		return mv;
	}

	@RequestMapping(UrlConstants.SYSTEM_NODE_CREATE)
	@ResponseBody
	public String nodeCreate(SystemNode node, String nname, Integer ntype, String parenid) {

		node.setNodeName(nname);
		node.setNodeType(ntype);
		if (StringUtil.isNotEmpty(parenid)) {

			SystemNode parent = menuService.findByNodeId(Long.valueOf(parenid));
			if (parent != null)
				node.setParent(parent);
		}
		menuService.save(node);
		return "创建成功";
	}

	@RequestMapping(UrlConstants.SYSTEM_NODE_UPDATE)
	@ResponseBody
	public String nodeUpdate(SystemNode node, String nname, Integer ntype) {

		node.setNodeName(nname);
		node.setNodeType(ntype);
		menuService.update(node);
		return "修改成功";
	}

	@RequestMapping(UrlConstants.SYSTEM_NODE_DEL)
	@ResponseBody
	public String nodeDel(Long nodeid) {

		menuService.del(nodeid);
		return "删除成功";
	}

	@RequestMapping(UrlConstants.SYSTEM_URL_INDEX)
	public ModelAndView urlIndex() {

		return new ModelAndView(TilesUtil.getPath(UrlConstants.SYSTEM_URL_INDEX));
	}

	@RequestMapping(UrlConstants.SYSTEM_URL_DATA)
	@ResponseBody
	public AjaxPage channelData(Integer pageNumber, Integer pageSize, final String sortName, final String sortOrder) {

		List<SpecificationCondition> conditions = new ArrayList<>();
		SpecificationHelper<Url> sh = new SpecificationHelper<>(conditions, sortOrder, sortName);
		Page<?> p = urlService.page(new PageRequest(pageNumber, pageSize), sh.createSpecification());
		return AjaxPageUtil.toAjaxPage(p.getTotalElements(), p.getContent());
	}

	@RequestMapping(UrlConstants.SYSTEM_URL_DEL)
	@ResponseBody
	public String channelData(@RequestBody List<Url> data) {
		urlService.del(data);
		return "删除成功";
	}

	@RequestMapping(UrlConstants.SYSTEM_USERGROUP_INDEX)
	public ModelAndView usergroupIndex(final UserGroup search) {
		ModelAndView mv = new ModelAndView(TilesUtil.getPath(UrlConstants.SYSTEM_USERGROUP_INDEX));
		return mv;
	}

	@RequestMapping(UrlConstants.SYSTEM_USERGROUP_DATA)
	@ResponseBody
	public AjaxPage usergroupData(Integer pageNumber, Integer pageSize, final UserGroup search, final String sortName,
			final String sortOrder) {

		String[] orders = { "codePath", "createTime" };

		Page<?> p = userGroupService.page(new PageRequest(pageNumber, pageSize), new Specification<UserGroup>() {

			@Override
			public Predicate toPredicate(Root<UserGroup> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

				List<Predicate> p = new ArrayList<Predicate>();
				p.add(cb.equal(root.get("logicStat"), LogicStat.NORMAL.getValue()));

				if (search.getCode() != null)
					p.add(cb.like(root.get("code").as(String.class), "%" + search.getCode() + "%"));

				if (search.getName() != null)
					p.add(cb.like(root.get("name").as(String.class), "%" + search.getName() + "%"));

				Predicate[] predicates = new Predicate[p.size()];
				p.toArray(predicates);

				query = query.where(predicates);
				if (StringUtil.isNotEmpty(sortName)) {
					switch (sortOrder) {
					case "asc":
						query.orderBy(cb.asc(root.get(sortName)));
						break;

					case "desc":
						query.orderBy(cb.desc(root.get(sortName)));
						break;
					}
				}
				return query.getGroupRestriction();
			}
		});

		return AjaxPageUtil.toAjaxPage(p.getTotalElements(), p.getContent());

	}

	@RequestMapping(UrlConstants.SYSTEM_USERGROUP_NEW)
	public ModelAndView userGroupnNew() {

		ModelAndView mv = new ModelAndView(UrlConstants.SYSTEM_USERGROUP_NEW);
		mv.addObject("selectParent", userGroupEm.listSelectParentForCreate());
		return mv;
	}

	@RequestMapping(UrlConstants.SYSTEM_USERGROUP_CREATE)
	@ResponseBody
	public String userGroupCreate(UserGroup userGroup) {

		userGroupService.create(userGroup);
		return "新建用户组成功";
	}

	@RequestMapping(UrlConstants.SYSTEM_USERGROUP_DEL)
	@ResponseBody
	public String userGroupDel(@RequestBody List<UserGroup> data) {

		userGroupService.del(data);
		return "删除用户组成功";
	}

	@RequestMapping(UrlConstants.SYSTEM_USERGROUP_VIEW)
	public ModelAndView userGroupView(Long userGroupId) {

		ModelAndView mv = new ModelAndView(UrlConstants.SYSTEM_USERGROUP_VIEW);
		mv.addObject("ug", userGroupEm.findOne(userGroupId));
		mv.addObject("selectParent", userGroupEm.listSelectParentForCreate());
		mv.addObject("isMenuList", IsMenu.toListValue());
		return mv;
	}

	@RequestMapping(UrlConstants.SYSTEM_USERGROUP_UPDATE)
	@ResponseBody
	public String userGroupUpdate(UserGroup update, String url) {

		UrlAction uc = urlActionEm.findByUrlAndLogicStat(url, LogicStat.NORMAL.getValue());
		if (uc != null)
			update.setUrlAction(uc);
		userGroupService.update(update);
		return "更新用户组信息成功";
	}

	@RequestMapping(UrlConstants.SYSTEM_USERGROUP_AUTOCOMPLETE_URLACTION)
	@ResponseBody
	public List<Autocomplete> autoUrl(String term) {

		return AutocompleteUtil.object2auto(urlActionEm.autoUrlAction(term));
	}

	@RequestMapping(UrlConstants.SYSTEM_URL_AUTOCOMPLETE)
	@ResponseBody
	public List<Autocomplete> autoUrl2(String term) {

		return AutocompleteUtil.object2auto(urlService.auto(term));
	}
}
